package org.dce.screencapturer.components;

import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.LayoutManager2;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class Toolbar 
	extends JPanel{

	public Toolbar(){
		setLayout(new PanelLayout());
	}
	
	public void addArea(String sectionName, Container area){
		
		BarSection barSection = new BarSection();
		barSection.setTitle(sectionName);
		barSection.setArea(area);
		
		add(barSection);

		invalidate();
	}

	public static class BarSection extends JPanel
		implements ActionListener{
		
		private TitleComponent title = new TitleComponent();
		private Component area;
		private boolean forcedToRetract = false;


		public BarSection(){
			setLayout(new BorderLayout(2,2));
			
			title.addActionListener(this);
			add(title,BorderLayout.SOUTH);

			setBorder(BorderFactory
				.createCompoundBorder(
					BorderFactory.createLineBorder(Color.BLACK), 
					BorderFactory.createEmptyBorder(2,2,2,2)));
		}
		
		public boolean isForcedToRetract() {
			return forcedToRetract;
		}

		public void setForcedToRetract(boolean forcedToRetract) {
			this.forcedToRetract = forcedToRetract;
		}
		
		public void actionPerformed(ActionEvent event){
			if (title.isToggled()){
				area.setVisible(false);
				remove(title);
				add(title,BorderLayout.WEST);
			} else {
				area.setVisible(true);
				remove(title);
				add(title,BorderLayout.SOUTH);
			}
			revalidate();
		}
		
		public JComponent getTitleLabel(){
			return title;
		}
		
		public void setTitle(String title){
			this.title.setText(title);
		}
		
		public void setArea(Component c){
			this.area = c;
			this.add(c,BorderLayout.CENTER);
		}

	}
	
	private static class TitleComponent extends JComponent{
		private String text;

		private boolean toggled = false;
		private List<ActionListener> listeners = new ArrayList<ActionListener>();
		private static final Insets INSETS = new Insets(0,0,0,0);
		public TitleComponent(){
			enableEvents(AWTEvent.MOUSE_EVENT_MASK);
			
		}
		
		public Insets getInsets(){
			return INSETS;
		}

		public void setText(String text) {
			this.text = text;
			update();
		}

		public boolean isToggled(){
			return toggled;
		}
		
		public void addActionListener(ActionListener listener){
			listeners.add(listener);
		}
		
		protected void toggle(){
			
			this.toggled = !toggled;
			
			update();
			
			ActionEvent event = new ActionEvent(this,ActionEvent.ACTION_PERFORMED,"toggle");
			for (ActionListener listener:listeners){
				listener.actionPerformed(event);
			}
		}
		
		private void update(){
			
			FontMetrics metrics = getFontMetrics(getFont());
			
			int stringWidth = metrics.stringWidth(text)+4;
			int height = metrics.getHeight()+metrics.getDescent();
			if (toggled){
				setPreferredSize(new Dimension(height,stringWidth));
			} else {
				setPreferredSize(new Dimension(stringWidth,height));
			}
			repaint();
		}
		
		protected void paintComponent(Graphics g){
			Graphics2D g2d = (Graphics2D)g;
			
			g2d.setFont(getFont());
			
			FontMetrics fm = g2d.getFontMetrics();

			final int width = getWidth();
			final int height = getHeight();
			final int stringWidth = fm.stringWidth(text);
			final int fontHeight = fm.getHeight();
			
			g2d.setColor(getBackground());
			g2d.fillRect(0,0,width-1,height-1);
			
			g2d.setColor(getForeground());

			if (toggled){
				
				g2d.rotate(-Math.PI/2,0,0);
				g2d.translate(-height,0);

				g2d.drawString(
						text, 
						(height-stringWidth)/2, 
						(width+fontHeight)/2-fm.getDescent());
			} else {
				g2d.drawString(
					text, 
					(width-stringWidth)/2, 
					(height+fontHeight)/2-fm.getDescent());
			}
		}
		
		protected void processMouseEvent(MouseEvent event){
			if (event.getID() == MouseEvent.MOUSE_PRESSED){
				toggle();
			}
			super.processMouseEvent(event);
		}
	}
	
	private static class PanelLayout implements LayoutManager2 {

		public void addLayoutComponent(Component comp, Object constraints) {}
		public void invalidateLayout(Container target) {}
		public void addLayoutComponent(String name, Component comp) {}
		public float getLayoutAlignmentX(Container target) {return 0;}
		public float getLayoutAlignmentY(Container target) {return 0;}
		public void removeLayoutComponent(Component comp) {}


		@Override
		public Dimension maximumLayoutSize(Container target) {
			
			Dimension dimension = new Dimension(0,0);
			
			Component[] components = target.getComponents();
			
			for (Component c: components){
				Dimension maximum = c.getMaximumSize();
				dimension.width+=maximum.width;
				dimension.height=Math.max(dimension.height, maximum.height);
			}
			
			dimension.width+=(2*(components.length-1));
			dimension.height+=4;
			
			return dimension;
		}


		@Override
		public void layoutContainer(Container parent) {
			
			Component[] components = parent.getComponents();
			
			int maxHeight = 0;
			
			for (Component c:components){
				maxHeight = Math.max(c.getPreferredSize().height, maxHeight);
			}
			
			Insets insets = parent.getInsets();
			
			int containerHeight = parent.getHeight() - insets.top - insets.bottom;
			
			maxHeight = Math.min(maxHeight, containerHeight);
			
			int offset = insets.left;

			for (Component c:parent.getComponents()){
				c.setSize(c.getPreferredSize().width,maxHeight);
				c.setLocation(offset,2+insets.top);
				offset+=c.getWidth()+2;
			}
		}

		@Override
		public Dimension minimumLayoutSize(Container parent) {
			Dimension dimension = new Dimension(0,0);
			
			Component[] components = parent.getComponents();

			for (Component c: components){
				Dimension minimum = c.getMinimumSize();
				dimension.width+=minimum.width;
				dimension.height=Math.max(dimension.height, minimum.height);
			}
			
			dimension.width+=(2*(components.length-1));
			dimension.height+=4;
			
			return dimension;
		}

		@Override
		public Dimension preferredLayoutSize(Container parent) {
			Dimension dimension = new Dimension(0,0);
			
			Component[] components = parent.getComponents();

			for (Component c: components){
				Dimension preferred = c.getPreferredSize();
				dimension.width+=preferred.width;
				dimension.height=Math.max(dimension.height, preferred.height);
			}
			
			dimension.width+=(2*(components.length-1));
			dimension.height+=4;
			
			return dimension;
		}

		
	}

}
